package com.aner.tester.executor;


import org.slf4j.Logger;
import com.aner.tester.utils.LoggerUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.annotation.PreDestroy;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * code generation task executor
 *
 * @author aner
 */
public class CodeGenExecutor
{
    private final Logger logger = LoggerUtils.getLogger(CodeGenExecutor.class);

    /**
     *  the size of the core thread
     */
    private int corePoolSize = 4;

    /**
     * max size of the thread that can be created
     */
    private int maxPoolSize = 16;

    /**
     * max capacity of task queue
     */
    private int queueCapacity = 100;

    /**
     * the time(second) of keep alive
     */
    private int keepAliveSeconds = 300;

    /**
     * task executor
     */
    private ThreadPoolTaskExecutor executor;

    private CodeGenExecutor(){
        executor = new ThreadPoolTaskExecutor();
        executor.setMaxPoolSize(maxPoolSize);
        executor.setCorePoolSize(corePoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setKeepAliveSeconds(keepAliveSeconds);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        // logger.info("code generator thread pool init.");
    }

    /**
     * execute task
     *
     * @param
     */
    public <T> Future<T> submit(Callable<T> task) {
        return executor.submit(task);
    }

    /**
     * execute task
     *
     * @param
     */
    public void execute(Runnable runnable)
    {
        executor.execute(runnable);
    }

    /**
     * execute task
     *
     * @param
     */
    public void execute(Runnable runnable, long startTimeout)
    {
        executor.execute(runnable, startTimeout);
    }

    /**
     * show down task pool
     */
    @PreDestroy
    public void destroy() {
        try
        {
            if (executor != null) {
                executor.shutdown();
            }
        }
        catch (Exception e)
        {
            logger.error(e.getMessage(), e);
        }
    }

    private static class CodeGenExecutorHolder {
        public static final CodeGenExecutor INSTANCE = new CodeGenExecutor();
    }

    public static CodeGenExecutor me() {
        return CodeGenExecutorHolder.INSTANCE;
    }
}
